home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / dev / misc / AmigaSDLsrc.lha / amisrc / SDL_gamma.c < prev    next >
C/C++ Source or Header  |  2001-04-29  |  6KB  |  243 lines

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
  4.  
  5.     This library is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU Library General Public
  7.     License as published by the Free Software Foundation; either
  8.     version 2 of the License, or (at your option) any later version.
  9.  
  10.     This library is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.     Library General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU Library General Public
  16.     License along with this library; if not, write to the Free
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19.     Sam Lantinga
  20.     slouken@devolution.com
  21. */
  22.  
  23. #ifdef SAVE_RCSID
  24. static char rcsid =
  25.  "@(#) $Id: SDL_gamma.c,v 1.1.2.12 2001/02/10 07:20:05 hercules Exp $";
  26. #endif
  27.  
  28. /* Gamma correction support */
  29.  
  30. #define USE_MATH_H    /* Used for calculating gamma ramps */
  31.  
  32. #ifdef USE_MATH_H
  33. #include <math.h>
  34. #endif
  35. #include <stdlib.h>
  36.  
  37. #include "SDL_error.h"
  38. #include "SDL_sysvideo.h"
  39.  
  40. #ifdef USE_MATH_H
  41. static void CalculateGammaRamp(float gamma, Uint16 *ramp)
  42. {
  43.     int i;
  44.  
  45.     /* 0.0 gamma is all black */
  46.     if ( gamma <= 0.0 ) {
  47.         for ( i=0; i<256; ++i ) {
  48.             ramp[i] = 0;
  49.         }
  50.         return;
  51.     } else
  52.     /* 1.0 gamma is identity */
  53.     if ( gamma == 1.0 ) {
  54.         for ( i=0; i<256; ++i ) {
  55.             ramp[i] = (i << 8) | i;
  56.         }
  57.         return;
  58.     } else
  59.     /* Calculate a real gamma ramp */
  60.     { int value;
  61.         gamma = 1.0f / gamma;
  62.         for ( i=0; i<256; ++i ) {
  63.             value = (int)(pow((double)i/256.0, gamma)*65535.0+0.5);
  64.             if ( value > 65535 ) {
  65.                 value = 65535;
  66.             }
  67.             ramp[i] = (Uint16)value;
  68.         }
  69.     }
  70. }
  71. static void CalculateGammaFromRamp(float *gamma, Uint16 *ramp)
  72. {
  73.     /* The following is adapted from a post by Garrett Bass on OpenGL
  74.        Gamedev list, March 4, 2000.
  75.      */
  76.     float sum = 0.0;
  77.     int i, count = 0;
  78.  
  79.     *gamma = 1.0;
  80.     for ( i = 1; i < 256; ++i ) {
  81.         if ( (ramp[i] != 0) && (ramp[i] != 65535) ) {
  82.             double B = (double)i / 256.0;
  83.             double A = ramp[i] / 65535.0;
  84.             sum += (float) ( log(A) / log(B) );
  85.             count++;
  86.         }
  87.     }
  88.     if ( count && sum ) {
  89.         *gamma = 1.0f / (sum / count);
  90.     }
  91. }
  92. #endif /* USE_MATH_H */
  93.  
  94. int SDL_SetGamma(float red, float green, float blue)
  95. {
  96.     int succeeded;
  97.     SDL_VideoDevice *video = current_video;
  98.     SDL_VideoDevice *this  = current_video;    
  99.  
  100.     succeeded = -1;
  101. #ifdef USE_MATH_H
  102.     /* Prefer using SetGammaRamp(), as it's more flexible */
  103.     {
  104.         Uint16 ramp[3][256];
  105.  
  106.         CalculateGammaRamp(red, ramp[0]);
  107.         CalculateGammaRamp(green, ramp[1]);
  108.         CalculateGammaRamp(blue, ramp[2]);
  109.         succeeded = SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]);
  110.     }
  111. #else
  112.     SDL_SetError("Gamma correction not supported");
  113. #endif
  114.     if ( (succeeded < 0) && video->SetGamma ) {
  115.         SDL_ClearError();
  116.         succeeded = video->SetGamma(this, red, green, blue);
  117.     }
  118.     return succeeded;
  119. }
  120.  
  121. /* Calculating the gamma by integrating the gamma ramps isn't exact,
  122.    so this function isn't officially supported.
  123. */
  124. int SDL_GetGamma(float *red, float *green, float *blue)
  125. {
  126.     int succeeded;
  127.     SDL_VideoDevice *video = current_video;
  128.     SDL_VideoDevice *this  = current_video;    
  129.  
  130.     succeeded = -1;
  131. #ifdef USE_MATH_H
  132.     /* Prefer using GetGammaRamp(), as it's more flexible */
  133.     {
  134.         Uint16 ramp[3][256];
  135.  
  136.         succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]);
  137.         if ( succeeded >= 0 ) {
  138.             CalculateGammaFromRamp(red, ramp[0]);
  139.             CalculateGammaFromRamp(green, ramp[1]);
  140.             CalculateGammaFromRamp(blue, ramp[2]);
  141.         }
  142.     }
  143. #else
  144.     SDL_SetError("Gamma correction not supported");
  145. #endif
  146.     if ( (succeeded < 0) && video->GetGamma ) {
  147.         SDL_ClearError();
  148.         succeeded = video->GetGamma(this, red, green, blue);
  149.     }
  150.     return succeeded;
  151. }
  152.  
  153. int SDL_SetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  154. {
  155.     int succeeded;
  156.     SDL_VideoDevice *video = current_video;
  157.     SDL_VideoDevice *this  = current_video;    
  158.     SDL_Surface *screen = SDL_PublicSurface;
  159.  
  160.     /* Verify the screen parameter */
  161.     if ( !screen ) {
  162.         SDL_SetError("No video mode has been set");
  163.         return -1;
  164.     }
  165.  
  166.     /* Lazily allocate the gamma tables */
  167.     if ( ! video->gamma ) {
  168.         SDL_GetGammaRamp(0, 0, 0);
  169.     }
  170.  
  171.     /* Fill the gamma table with the new values */
  172.     if ( red ) {
  173.         memcpy(&video->gamma[0*256], red, 256*sizeof(*video->gamma));
  174.     }
  175.     if ( green ) {
  176.         memcpy(&video->gamma[1*256], green, 256*sizeof(*video->gamma));
  177.     }
  178.     if ( blue ) {
  179.         memcpy(&video->gamma[2*256], blue, 256*sizeof(*video->gamma));
  180.     }
  181.  
  182.     /* Gamma correction always possible on split palettes */
  183.     if ( (screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) {
  184.         SDL_Palette *pal = screen->format->palette;
  185.  
  186.         /* If physical palette has been set independently, use it */
  187.         if(video->physpal)
  188.                 pal = video->physpal;
  189.               
  190.         SDL_SetPalette(screen, SDL_PHYSPAL,
  191.                    pal->colors, 0, pal->ncolors);
  192.         return 0;
  193.     }
  194.  
  195.     /* Try to set the gamma ramp in the driver */
  196.     succeeded = -1;
  197.     if ( video->SetGammaRamp ) {
  198.         succeeded = video->SetGammaRamp(this, video->gamma);
  199.     } else {
  200.         SDL_SetError("Gamma ramp manipulation not supported");
  201.     }
  202.     return succeeded;
  203. }
  204.  
  205. int SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  206. {
  207.     SDL_VideoDevice *video = current_video;
  208.     SDL_VideoDevice *this  = current_video;    
  209.  
  210.     /* Lazily allocate the gamma table */
  211.     if ( ! video->gamma ) {
  212.         video->gamma = malloc(3*256*sizeof(*video->gamma));
  213.         if ( ! video->gamma ) {
  214.             SDL_OutOfMemory();
  215.             return -1;
  216.         }
  217.         if ( video->GetGammaRamp ) {
  218.             /* Get the real hardware gamma */
  219.             video->GetGammaRamp(this, video->gamma);
  220.         } else {
  221.             /* Assume an identity gamma */
  222.             int i;
  223.             for ( i=0; i<256; ++i ) {
  224.                 video->gamma[0*256+i] = (i << 8) | i;
  225.                 video->gamma[1*256+i] = (i << 8) | i;
  226.                 video->gamma[2*256+i] = (i << 8) | i;
  227.             }
  228.         }
  229.     }
  230.  
  231.     /* Just copy from our internal table */
  232.     if ( red ) {
  233.         memcpy(red, &video->gamma[0*256], 256*sizeof(*red));
  234.     }
  235.     if ( green ) {
  236.         memcpy(green, &video->gamma[1*256], 256*sizeof(*green));
  237.     }
  238.     if ( blue ) {
  239.         memcpy(blue, &video->gamma[2*256], 256*sizeof(*blue));
  240.     }
  241.     return 0;
  242. }
  243.